#pragma once

#include "fs_algo.h"
#include "Data.h"

#include "Extractor.h"
#include "GlobalExtractor.h"
#include "ResourceExtractor.h"
#include "Model.h"
#include "Config.h"

#define BEAM_SIZE 40

struct Hypo
{
	double score;
	int type_idx;
	int pre_idx;
	Hypo() {}
	Hypo(int t, int p, double s):type_idx(t),pre_idx(p),score(s) {}
	bool operator <(const Hypo& rhs) const { return score < rhs.score; }
	bool operator >(const Hypo& rhs) const { return score > rhs.score; }
	bool operator==(const Hypo& rhs) const { return score ==rhs.score; }
};

typedef vector<Hypo> Beam;

class BeamSearcher
{
public:
	BeamSearcher(Config* c, CModel* m, Extractor* e, GlobalExtractor* ge, ResourceExtractor* re)
		:config(c),model(m),extractor(e),g_extractor(ge),r_extractor(re) {}
	void search(const string& src, string& best, vector<string>& nbest);
private:
	bool transfer_legal(const string& type_from, const string& type_to);
	void init_sent(const string& src);
	void first_stage(const vector<vector<string> >& features_res);
	void beam_search(int cur, const vector<vector<string> >& features_res);
	void get_kth_tag_seq(int kth_idx, vector<string>& tag_seq);
	void output_kth_best(int kth_idx, string& result);
	void output_nbest(vector<string>& nbest);
	void output_beam(int beam_idx);
	void output_feature_score_info(const char* path);
private:
	vector<string> words;
	vector<string> forms;
	vector<Beam> hypos;
private:
	Config* config;
	CModel* model;
	Extractor* extractor;
	GlobalExtractor* g_extractor;
	ResourceExtractor* r_extractor;
};
